/*
Copyright (C) 2013-2021 LZE
C--
A Strange Programming Language
Made by:Lzexmpoane
*/
#include<bits/stdc++.h>
#include "./include/throw_error.h"
#include "./include/memory.h"
#include "./include/value_type.h"
#include "./include/location.h"
#include "./include/operation.h"
#include "./include/definition.h"
#include "./include/feedback.h"
#include "./include/init_file.h"
using namespace std;
value_wtype fun_run(string func_name,string func_type,int point){
	return_value.clear();
	return_value.type=func_type;
	pw p;
	do{
		p=read_word(point);
		if(p.word=="/"){
			point=p.e_p;
			p=read_word(point);
			if(p.word=="*"){
				while(1){
					point=p.e_p;
					p=read_word(point);
					if(p.word=="*"){
						point=p.e_p;
						p=read_word(point);
						if(p.word=="/")break;
					}
					if(point>length_of_file)prog_error(point,7);
				}
			}
			if(p.word=="/"){
				while(1){
					point=p.e_p;
					p=read_word(point);
					if(p.word=="\n"||p.word=="\0")break;
					if(point>length_of_file)prog_error(point,7);
				}
			}
		}
		if(p.word=="#"){
			do{
				point=p.e_p;
				p=read_word(point);
			}while(!((file[point]>='a'&&file[point]<='z')||
			(file[point]>='A'&&file[point]<='Z')||file[point]=='_'));
			if(p.word=="PAUSE"){
				printf("--------------------\n");
				printf("Point:%d\n",point);
				system("pause");
			}
		}
		else if(p.word=="}"){
			if(prog_stack.top().word=="{")prog_stack.pop();
			else prog_error(prog_stack.top().s_p,4);
		}
		else if(p.word==")"){
			while(!prog_stack.empty()&&
			prog_stack.top().word!="(")prog_stack.pop();
			if(!prog_stack.empty()&&
			prog_stack.top().word=="(")prog_stack.pop();
			else if(prog_stack.empty())prog_error(-1,5);
			else prog_error(prog_stack.top().s_p,5);
		}
		else if(p.word==key_words[1]){
			point=p.e_p;
			p=read_word(point);
			while(!((p.word[0]>='a'&&p.word[0]<='z')||
			(p.word[0]>='A'&&p.word[0]<='Z')||p.word[0]=='_')){
				point=p.e_p;
				p=read_word(point);
			}
			M[p.word]=value_wtype(key_words[1],init_for_int);
			prog_stack.push(p);
		}
		else if(p.word==key_words[2]){
			point=p.e_p;
			p=read_word(point);
			while(!((p.word[0]>='a'&&p.word[0]<='z')||
			(p.word[0]>='A'&&p.word[0]<='Z')||p.word[0]=='_')){
				point=p.e_p;
				p=read_word(point);
			}
			M[p.word]=value_wtype(key_words[2],init_for_char);
			prog_stack.push(p);
		}
		else if(p.word==key_words[3]){
			point=p.e_p;
			p=read_word(point);
			while(!((p.word[0]>='a'&&p.word[0]<='z')||
			(p.word[0]>='A'&&p.word[0]<='Z')||p.word[0]=='_')){
				point=p.e_p;
				p=read_word(point);
			}
			M[p.word]=value_wtype(key_words[3],init_for_string);
			prog_stack.push(p);
		}
		else if(p.word==key_words[5]){
			if(M[prog_stack.top().word].type==key_words[1]){
				while(!((p.word[0]>='0'&&p.word[0]<='9')||p.word[0]=='-')){
					point=p.e_p;
					p=read_word(point);
				}
				M[prog_stack.top().word]=
				value_wtype(key_words[1],stoll(p.word));
			}
			else if(M[prog_stack.top().word].type==key_words[2]){
				point=p.e_p;
				p=read_char(point);
				M[prog_stack.top().word]=
				value_wtype(key_words[2],p.word);
			}
			else if(M[prog_stack.top().word].type==key_words[3]){
				point=p.e_p;
				p=read_string(point);
				M[prog_stack.top().word]=
				value_wtype(key_words[3],p.word);
			}
		}
		else if(p.word==key_words[6]){
			while(p.word!="("){
				point=p.e_p;
				p=read_word(point);
			}
			while(!((file[point]>='a'&&file[point]<='z')||
	(file[point]>='A'&&file[point]<='Z')||file[point]=='_'
	||file[point]=='-'||(file[point]>='0'&&file[point]<='9')||p.word[0]=='\"')){
				point=p.e_p;
				p=read_word(point);
			}
			if((p.word[0]>='0'&&p.word[0]<='9')||p.word[0]=='-')cout<<p.word;
			else if(p.word[0]=='\"'){
				p=read_string(point);
				cout<<p.word;
			}
			else if(M[p.word].type==key_words[1])printf("%lld",M[p.word].int_type);
			else if(M[p.word].type==key_words[2])cout<<M[p.word].char_type;
			else if(M[p.word].type==key_words[3])cout<<M[p.word].string_type;
			while(p.word!=")"){
				point=p.e_p;
				p=read_word(point);
			}
		}
		else if(p.word==key_words[7]){
			while(p.word!="("){
				point=p.e_p;
				p=read_word(point);
			}
			while(!((file[point]>='a'&&file[point]<='z')||
	(file[point]>='A'&&file[point]<='Z')||file[point]=='_'
	||file[point]=='-'||(file[point]>='0'&&file[point]<='9')||p.word[0]=='\"')){
				point=p.e_p;
				p=read_word(point);
			}
			if(M[p.word].type==key_words[1]){
				sole_buffer.type=key_words[1];
				scanf("%lld",&sole_buffer.int_type);
				buffer.push(sole_buffer);
				M[p.word]=buffer.front();
				buffer.pop();
			}
			else if(M[p.word].type==key_words[2]){
				sole_buffer.type=key_words[2];
				sole_buffer.char_type=getchar();
				buffer.push(sole_buffer);
				M[p.word]=buffer.front();
				buffer.pop();
			}
			else if(M[p.word].type==key_words[3]){
				sole_buffer.type=key_words[3];
				cin>>sole_buffer.string_type;
				buffer.push(sole_buffer);
				M[p.word]=buffer.front();
				buffer.pop();
			}
			while(p.word!=")"){
				point=p.e_p;
				p=read_word(point);
			}
		}
		else if(p.word==key_words[8])cout<<endl;
		else if(p.word==";"){
			while(!prog_stack.empty()&&
			prog_stack.top().word!=";"&&
			prog_stack.top().word!="{")prog_stack.pop();
		}
		else if(p.word==key_words[9]){
			do{
				point=p.e_p;
				p=read_word(point);
			}while(!((file[point]>='a'&&file[point]<='z')||
			(file[point]>='A'&&file[point]<='Z')||file[point]=='_'));
//			S[p.word]=p.e_p;
		}
		else if(p.word==key_words[10]){
			do{
				point=p.e_p;
				p=read_word(point);
			}while(!((file[point]>='a'&&file[point]<='z')||
			(file[point]>='A'&&file[point]<='Z')||file[point]=='_'));
			point=S[p.word];
			continue;
		}
		else if(p.word==key_words[13]){
			do{
				point=p.e_p;
				p=read_word(point);
			}while(!((p.word[0]>='0'&&p.word[0]<='9')||p.word[0]=='-'));
			exit(stoll(p.word));
		}
		else if(p.word==key_words[14]){
			while(p.word!="("){
				point=p.e_p;
				p=read_word(point);
			}
			while(!((file[point]>='a'&&file[point]<='z')||
	(file[point]>='A'&&file[point]<='Z')||file[point]=='_'
	||file[point]=='-'||(file[point]>='0'&&file[point]<='9')||p.word[0]=='\"')){
				point=p.e_p;
				p=read_word(point);
			}
			if((p.word[0]>='0'&&p.word[0]<='9')||p.word[0]=='-'){
				assignment(return_value,stoll(p.word));
				return return_value;
			}
			else if(p.word[0]=='\"'){
				p=read_string(point);
				assignment(return_value,p.word);
				return return_value;
			}
			else if(M[p.word].type==key_words[1]){
				assignment(return_value,M[p.word].int_type);
				return return_value;
			}
			else if(M[p.word].type==key_words[2]){
				assignment(return_value,M[p.word].char_type);
				return return_value;
			}
			else if(M[p.word].type==key_words[3]){
				assignment(return_value,M[p.word].string_type);
				return return_value;
			}
			while(p.word!=")"){
				point=p.e_p;
				p=read_word(point);
			}
		}
		else if(p.word!=" "&&p.word!="\n"&&p.word!="\t")prog_stack.push(p);
		point=p.e_p;
	}while(!prog_stack.empty());
	return return_value;
}
int main(int argc,char *argv[]){
	file.resize(file_limit,'\0');
	ifstream fin;char ch;
	if(argc<2)prog_error(-1,6);
	if(argv[1][0]=='-')console_feed(argc,argv);
	fin.open(argv[1],ios::in);
	if(!fin.good())prog_error(-1,1);
	if(fin.eof())prog_error(-1,2);
	while(fin.peek()!=EOF){
		fin.get(ch);
		file[length_of_file]=ch;
		length_of_file++;
	}
	unsigned long long point=file.find(key_words[0]);
	if(point==string::npos)prog_error(-1,3);
	init_file(point);
	while(!prog_stack.empty())prog_stack.pop();
	fun_run(key_words[0],key_words[1],point);
	return 0;
}
